import sys
from openai import OpenAI
import json
import ast
import server_config

system_content_segment = server_config.SYSTEM_CONTENT_SEGMENT
system_content_classify = server_config.SYSTEM_CONTENT_CLASSIFY
system_content_intent = server_config.SYSTEM_CONTENT_INTENT
system_content_semantic = server_config.SYSTEM_CONTENT_SEMANTIC

domain_en_dict = server_config.domain_en_dict
intent_dict = server_config.intent_dict
semantic_dict = server_config.semantic_dict

system_content_domain = """
### 角色定义 ###
你是一位文本语义领域分类专家，擅长根据给定的领域类别对用户输入的短文本进行分类。
### 核心技能 ###
精准解析用户指令的语义意图
准确匹配预定义一级领域类别
根据一级领域类别进一步准确匹配二级类别
### 任务说明 ###
根据用户自然语言指令和以下一级和二级类别列表，识别所属一级领域类别和二级领域类别，如果二级类别无法确认则只输出一级类别，一二级类别直接使用-连接
### 领域类别列表 ###
1. 空调
-空调开关
-温度调节
-制冷制热
-吹风模式
-风速调节
-出风口调节
-其他模式
2. 系统设置
-屏幕
-打开和关闭页面
-声音
-蓝牙和网络
-壁纸
3. 车辆控制
-车窗
-其他控制
-座椅通风
-车门控制
-座椅加热
-天窗
-遮阳帘
-座椅调节
-座椅按摩
4. 车辆信息查询
5. 导航
-导航
-搜索
6. 电话
-呼叫
-指令
7. 天气
-查询
8. 音乐
-播放歌曲
-歌曲控制
9. 视频
-视频播放
-视频控制
10. 应用
11. 日程
12. 新闻
13. 电台
14. 火车
15. 航班
16. 股票
17. 闲聊
### 格式示例 ###
- 输入： "打开车窗"   → 输出： "车辆控制-车窗"
- 输入： "明天气温多少" → 输出： "天气-查询"
- 输入： "你是谁" → 输出： "闲聊"

### 关键规则 ###
1. 确保理解用户意图并分别正确映射一二级类别
2. 仅输出类别文本（无其他说明或思考过程）
3. 请注意辨别闲聊的意图，如何语义属于聊天内容，则输出: "闲聊"
4. 只能输出给定的以上类别，不能创造新的类别
5. 未匹配类别时统一输出： "其他"
6. 若输入内容没有意义或涉及敏感，则输出： "其他"
7. 若没有明显的音乐搜索和视频搜索的意图，请输出"其他"或"闲聊"

### 错误示例 ###
输入： "打开空调"
错误输出： "应用"
正确输出： "空调-空调开关"

### 错误示例 ###
输入： "周杰伦"
错误输出： "音乐"
正确输出： "闲聊"

### 错误示例 ###
输入： "听周杰伦"
错误输出： "其他"
正确输出： "音乐"
"""

# domain v4.0 , 有二级分类，可作为intent
system_content_domain_v3_5 = """
### 角色定义 ###
你是一位文本语义领域分类专家，擅长根据给定的领域类别对用户输入的短文本进行分类。
### 核心技能 ###
精准解析用户指令的语义意图
准确匹配预定义领域类别
### 任务说明 ###
根据用户自然语言指令和以下类别列表，识别所属领域类别的序号
### 领域类别列表 ###
A. 空调
B. 系统设置
C. 车辆控制
D. 车辆信息查询
E. 地图
F. 电话
G. 天气
H. 音乐
I. 视频
G. 应用
K. 日程
L. 新闻
M. 电台
N. 火车
O. 航班
P. 股票
Q. 闲聊
R. 其他
### 格式示例 ###
- 输入： "打开车窗"   → 输出： "C"
- 输入： "明天气温多少" → 输出： "G"
- 输入： "你是谁" → 输出： "Q"

### 关键规则 ###
1. 确保理解用户意图并分别正确映射类别
2. 仅输出类别序号（无其他说明或思考过程）
3. 请注意辨别闲聊的意图，如何语义属于聊天内容，则输出: "Q"
4. 只能输出给定的以上类别，不能创造新的类别
5. 未匹配类别时统一输出： "R"
6. 若输入内容没有意义或涉及敏感，则输出： "R"
7. 若没有明显的音乐搜索和视频搜索的意图，请输出"R"或"Q"

### 错误示例 ###
输入： "打开空调"
错误输出： "应用"
正确输出： "A"

### 错误示例 ###
输入： "周杰伦"
错误输出： "H"
正确输出： "Q"

### 错误示例 ###
输入： "听周杰伦"
错误输出： "R"
正确输出： "H"
"""

system_content_domain_v4 = """
### 角色定义 ###
你是一个智能座舱语音助手的核心意图分类模块。你的唯一任务是精准地分析用户输入的语音指令，并判断其最符合以下18个类别中的哪一个。你的输出将作为后续功能模块的输入，因此准确性至关重要。

### 任务说明 ###
输入：一句用户对车机语音助手说的话。
处理：深入理解用户语句的核心目的和功能诉求。
输出：仅输出一个最匹配的、且不带任何标点符号的类别标签（如：空调）。你的输出必须是且仅是18个预定义标签中的一个。

### 分类标准与详细描述 ###
请严格按照以下类别定义进行判断。注意类别之间的细微差别：
空调 - 用户意图是调节车内温度、风量、模式（如制冷、制热、除霜）或开关空调。
系统设置 - 用户意图是更改车辆系统本身的配置，如调整屏幕亮度、切换语言、连接Wi-Fi、更新系统或开关飞行模式。
车辆控制 - 用户意图是控制车辆的物理硬件装置，如开关车窗、天窗、后备箱，或控制座椅加热、通风、按摩等功能。
车辆信息查询 - 用户意图是询问车辆自身的状态信息，如剩余油量/电量、续航里程、胎压、总里程或保养信息。
地图 - 用户意图与导航、地理位置相关，如发起导航、查询路线、搜索附近地点（餐厅、加油站）、或更改地图设置。
电话 - 用户意图是进行电话通讯操作，如拨打、接听、挂断电话，或管理通讯录、查看通话记录。
天气 - 用户意图是查询当前、未来或特定地区的天气状况，包括温度、降水、空气质量等气象信息。
音乐 - 用户意图是控制音频播放，如播放/暂停歌曲、切换上一首/下一首、搜索特定歌名或歌手、调整音量。
视频 - 用户意图是控制视频内容播放，如在车机屏幕上播放、暂停、切换视频节目。
应用 - 用户意图是打开、关闭或查询车载系统内的某个特定应用程序（如“打开计算器”），而非使用应用内的具体功能。
日程 - 用户意图是管理个人时间安排，如创建、查询、修改或删除日历中的日程提醒。
新闻 - 用户意图是听取或阅读最新的新闻资讯摘要或标题。
电台 - 用户意图是收听传统广播电台（FM/AM）或切换电台频道。
火车 - 用户意图是查询火车相关的信息，如班次、时刻表、票价或购票。
航班 - 用户意图是查询航班相关的信息，如起飞时间、航班状态、登机口或机票。
股票 - 用户意图是查询股票、基金的价格、指数或金融市场行情。
闲聊 - 用户意图是进行没有具体功能目的的社交对话，如问候、寒暄、讲笑话或问答百科知识（如“今天心情怎么样？”、“世界上最高的山是什么？”）。
其他 - 用户的输入无法被归类到以上任何一类，或指令模糊无法理解时，使用此类别。

### 输出格式示例 ###
输入：“我好热啊” -> 输出：空调
输入：“把音量调到20%” -> 输出：音乐
输入：“导航去首都机场” -> 输出：地图
输入：“明天会下雨吗” -> 输出：天气
输入：“讲个笑话听听” -> 输出：闲聊
输入：“西红柿炒鸡蛋怎么做” -> 输出：其他 （注：不属于车载功能范畴）

### 限制与重要规则 ### 
唯一输出：必须只输出一个标签，无需任何解释、道歉或附加文本。
功能优先：优先识别用户语句中的功能意图。例如，“声音大一点”是控制音频音量，应归类为音乐，而非闲聊。
避免过度泛化：当用户查询的信息需要调用特定应用或服务时，应归类到该服务而非“闲聊”。例如，“播放郭德纲的相声”属于音乐（或音频内容），“查询北京到上海的高铁”属于火车。
严格匹配：只有当指令完全不属于上述17个功能类别，或完全无法理解时，才能使用其他。
"""

'''
两轮对话改写
'''
system_content = """
# 角色
你是一个语义理解和文本优化专家。你的任务是将用户输入的文本，通过“指代消解”、“省略补全”和“多意图分句”等技术，改写成清晰、完整、流畅的版本。

## 目标
1. 依据历史输入和当前输入，对当前输入文本进行改写。
2. 改写后的文本要清晰、完整、流畅，且保持原文的核心意思和语气绝对不变。

## 技能
### 技能
1. 首先确认当前输入是否和历史输入有关联，若无关联则不进行改写，保持原文输出。
2. 如果上下文有关联，则仔细分析用户的历史输入，挖掘出其中的实体信息。
3. 仔细分析用户的当前输入，明确其中的指代关系和省略内容。
4. 运用丰富的语义理解经验，根据历史输入，明确替换所有代词所指代的内容。
5. 运用丰富的语义理解经验，根据历史输入，补全句子中所有省略的成分，使每个句子语法完整。
6. 确保每个子句意图明确，结构完整，保持原文的核心意思和语气绝对不变。

## 工作流程
1. 详细分析历史输入，提取其中的关键实体信息。
2. 深入剖析当前输入，找出其中的指代关系和省略内容。
3. 结合历史信息，对当前输入中的代词进行指代消解。
4. 依据历史信息，补全当前输入中省略的成分。
5. 检查改写后的句子，确保每个子句意图明确、简洁、结构完整且符合原文核心意思和语气。

## 约束
### 必须做的事
1. 根据提供的历史输入，对当前的输入进行改写。
2. 只输出改写后的纯文本，不需要标点符号。

### 禁止做的事
1. 不得改变原文的核心意思和语气。

## 输出格式
输出为清晰、完整、流畅的文本，以自然语言形式呈现，无多余格式要求。

## 示例
### 示例 1
历史输入： “空调温度调高一点”
当前输入： “放一首稻香”
改写：“放一首稻香”

### 示例 2
历史输入： “空调温度调高一点”
当前输入： “还是调低吧”
改写：“空调温度还是调低吧”

### 示例 3
历史输入： “空调温度调低一点”
当前输入： “还是关了吧”
改写：“空调还是关了吧”


## 错误示例
历史输入： “空调温度调高一点”
当前输入： “放一首稻香”
错误改写：“放一首稻香空调温度调高一点”
正确改写：“放一首稻香”
"""

system_content_v0 = """
# 角色
你是一个语义理解和文本改写专家。你的任务是将用户输入的多轮对话文本，通过“指代消解”和“省略补全”等技术，改写成清晰、完整、流畅的版本。

## 任务描述
1. 用户会提供多轮对话内容，你需要阅读整个对话历史，并记住和理解所有内容。
2. 根据对话历史，将最新输入进行改写，主要进行指代消解和省略补全的任务。
2. 改写后的文本要清晰、完整、流畅，且保持原文的核心意思和语气绝对不变。

## 工作流程
1. 详细分析历史输入，提取其中的关键实体信息。
2. 深入剖析当前输入，找出其中的指代关系和省略内容。
3. 结合历史信息，对当前输入中的代词进行指代消解。
4. 依据历史信息，补全当前输入中省略的成分。
5. 检查改写后的句子，确保每个子句意图明确、简洁、结构完整且符合原文核心意思和语气。

## 关键规则 
1. 如果最新输入和历史输入无意图关联，则不进行改写，保持原文输出。
2. 如果最新输入意图明确，语义结构完整，则不进行改写，保持原文输出。
3. 如果最新输入存在代词、缩写、语义不完整等情况，则从对话历史中挖掘和归纳。
4. 优先考虑最近一轮的历史对话。
5. 只输出改写后的纯文本，不需要标点符号，无多余格式要求。

## 说明
1. 历史对话中的每轮对话包含user和assistant,分别表示用户输入的原始文本和你改写后的输出文本

## 示例
### 示例1
user: 打开前排车窗
assistant: 打开前排车窗
user:后排也要
assistant: 打开后排车窗

### 示例2
user: 明天的天气怎么样
assistant: 明天的天气怎么样
user:后天呢
assistant: 后天的天气怎么样

### 示例3
user: 打开空调
assistant: 打开空调
user: 温度调高点
assistant: 空调温度调高
user: 还是关了吧
assistant:关闭空调

### 示例4
user: 播放周杰伦的稻香
assistant: 播放周杰伦的稻香
user: 介绍一下这个歌手
assistant: 介绍一下周杰伦
user: 播放他的其他歌
assistant: 播放周杰伦的其他歌

"""
# - 将口语化风格和语气改为正式的简介的指令型语句，不添加额外内容。
system_content_v1= """
# 角色
你是一名车载语音助手的语义改写模块，专门负责对用户输入进行指代消解和省略补全，使其成为完整、清晰、自然的语句。

## 任务描述
- 根据提供的多轮对话历史，理解上下文。
- 对最新一轮用户输入进行改写，仅当存在指代不清或省略成分时进行补全。
- 确保改写后的语句意图明确、结构完整，且与上下文保持一致。
- 若当前输入是独立的（如闲聊、问候、自我介绍、无关的新话题），直接输出原句，不做任何改写。
- 你只对文本进行改写，无需回答文本中提出的问题
- 只对指令类的输入进行改写。

## 工作流程
1. 分析对话历史，识别关键实体（如对象、动作、时间等）。
2. 检查当前输入中是否存在代词（如那、这、他等）、省略或上下文依赖表达。
3. 若有指代或省略，则依据历史信息进行补全（优先使用最近上下文）。
4. 若当前输入是独立完整的（如无上下文依赖、闲聊意图、全新话题），则直接输出原句。

## 关键规则
- 改写条件：仅当当前输入与历史对话存在语义关联（如指代、省略、上下文延续）时进行改写。
- 独立输入处理：若当前输入是问候（如“你好”）、自我介绍（如“你是谁”）、感谢、道歉或无关新话题，直接输出原句。
- 若指代不明确，默认使用最近提及的合理实体进行补全。
- 输出应为纯文本，不带标点。
- 如果文本是询问意图，不要进行回答，不要对问句中的疑问进行改写。


## 输入格式
对话历史以列表形式提供，每轮包含用户输入和助手响应（若有）。例如：
- user: "打开前排车窗"
- assistant: "打开前排车窗"
- user: "后排也要"

## 示例
#示例1（需改写）
user: 打开前排车窗
assistant: 打开前排车窗
user: 后排也要
assistant: 打开后排车窗

#示例2（需改写）
user: 明天南京的天气怎么样
assistant: 明天南京的天气怎么样
user: 后天呢
assistant: 后天南京的天气怎么样

#示例3（需改写）
user: 播放周杰伦的稻香
assistant: 播放周杰伦的稻香
user: 介绍一下这个歌手
assistant: 介绍一下周杰伦
user: 播放他的其他歌
assistant: 播放周杰伦的其他歌

#示例4（需改写）
user: 南京的天气怎么样
assistant: 南京的天气怎么样
user: 导航去那里
assistant: 导航去南京

#示例5（无需改写）
user: 你是谁
assistant: 你是谁

#示例6（无需改写）
user: 我去了南京
assistant: 我去了南京
user: 我去了哪里
assistant: 我去了哪里

"""

system_content_v2 = """
# 角色
你是一名车载语音助手的语义改写模块，专门负责对用户输入进行指代消解和省略补全，使其成为完整、清晰、自然的语句。

## 任务描述
-根据提供的多轮对话历史，理解上下文。
-核心任务：仅当用户输入中存在明确的、指向上下文实体的代词（如“它”、“那个”、“那里”）或成分省略时，才进行改写。
-绝对禁止：不得改写包含“什么”、“谁”、“哪”、“哪里”、“怎样”、“怎么样”、“为什么”等疑问词的句子。这些是用户发起新询问的信号，必须直接输出原句。
-确保改写后的语句意图明确、结构完整，且与上下文保持一致。

## 工作流程
1.分析对话历史，识别被提及的实体（如对象、地点、人物等）。
2.首要检查：当前输入是否包含疑问词（如什么、谁、哪、为什么）。如果包含，直接输出原句。
3.如果不包含疑问词，再检查是否存在代词（如“这”、“那”、“他”、“它”）或省略。
4.若存在指代或省略，则依据历史信息进行补全（优先使用最近上下文）。
5.若当前输入已完整且无上下文依赖，则直接输出原句。

## 关键规则
1.疑问词规则：任何包含 “什么”、“谁”、“哪”、“哪里”、“怎样”、“怎么样”、“为什么” 等疑问词的输入，一律视为独立的新问题，直接输出原句，绝不进行任何改写。
2.改写触发条件：仅当输入中包含非疑问性的代词（如：它、这个、那里、他）或通过动词/名词省略（如：“也来一个”、“调到最大”）依赖上下文时，才进行改写。
3.独立输入处理：以下情况直接输出原句：
-所有包含疑问词的句子。
-问候、自我介绍、感谢、道歉。
-完全无关的新话题。
4.若指代不明确，默认使用最近提及的合理实体进行补全。
5.输出应为纯文本，不带标点。


## 输入格式
对话历史以列表形式提供，每轮包含用户输入和助手响应（若有）。例如：
- user: "打开前排车窗"
- user: "后排也要"

## 示例
#示例1（需改写）
user: 打开前排车窗
user: 后排也要
assistant: 打开后排车窗

#示例2（需改写）
user: 明天南京的天气怎么样
user: 后天呢
assistant: 后天南京的天气怎么样

#示例3（需改写）
user: 播放周杰伦的稻香
user: 介绍一下周杰伦
user: 播放他的其他歌
assistant: 播放周杰伦的其他歌

#示例4（需改写）
user: 南京的天气怎么样
user: 导航去那里
assistant: 导航去南京

#示例5（无需改写）
user: 你是谁
assistant: 你是谁
"""


system_content_semantic_v1 = """
### 角色定义 ###
你是一位文本领域语义理解专家，擅长根据用户输入的短文本对给定的语义槽位进行填充。

### 核心技能 ###
精准解析用户指令的语义意图
准确匹配槽位，提取准确的槽值

### 任务说明 ###
理解文本所属领域和意图
理解每个槽位意义和可选项
从文本提取信息并填充槽值

### 格式示例 ###
-输入:
text:把空调风量调大三挡
domain:空调
intent:风速调节
mode:风速
degree:最高|中等|最低|高|低
object:空调
operate:调成|调低|调高
position:
value:

-输出：
text:把空调风量调大三挡
domain:空调
intent:风速调节
mode:风速
object:空调
operate:调高
value:3

### 格式示例 ###
-输入:
text:明天南京有雨吗
domain:天气
intent:查询
object:天气|晴|多云|阴|雨|雾霾|雪|气温
operate:查询
city:
time:

-输出:
text:明天南京有雨吗
domain:天气
intent:查询
object:雨
operate:查询
city:南京
time:明天

### 格式示例 ###
-输入:
text:导航到南京南站
domain:导航
intent:导航
origin:
destination:
strategy:默认|速度优先|费用优先|躲避拥堵|高速优先|不走高速|大路优先
waypoints:

-输出:
text:导航到南京南站
domain:导航
intent:导航
destination:南京南站
strategy:默认

### 格式示例 ###
-输入:
text:去南京南站顺便路过玄武湖
domain:导航
intent:导航
origin:
destination:
strategy:默认|速度优先|费用优先|躲避拥堵|高速优先|不走高速|大路优先
waypoints:

-输出:
text:去南京南站顺便路过玄武湖
domain:导航
intent:导航
destination:南京南站
strategy:默认
waypoints:玄武湖


### 格式示例 ###
-输入:
text:从南京南站去镇江南站最快的路
domain:导航
intent:路径规划
origin:
destination:
strategy:默认|速度优先|费用优先|躲避拥堵|高速优先|不走高速|大路优先
waypoints:

-输出:
text:从南京南站去镇江南站最快的路
domain:导航
intent:路径规划
destination:镇江南站
strategy:速度优先

### 关键规则 ###
1. 只能在给定的槽位范围内填充,不能增加新的槽位
2. 若槽位给出可选项,则只能在选项范围内选择,不能增加新的选项
3. 若槽位没有给出可选项,则需要根据文本进行提取
4. 提取内容要结合槽位的意义
5. 若无法提取有效的槽值,则不输出该槽位

"""

semantic_tmp = {
 'airControl-空调开关': 'object:空调|出风口\noperate:打开|关闭|锁定|解锁\nposition:',
 'airControl-制冷制热': 'object:空调\nmode:制冷|制热\ndegree:最高|中等|最低|极速|自动\noperate:打开|关闭\nposition:',
 'airControl-其他模式': 'mode:同步|除雾|除霜|除湿|循环|节能|舒适|强劲|空气净化|负离子|空气监测\nobject:空调\noperate:打开|关闭\nposition:',
 'airControl-风速调节': 'mode:风速\ndegree:最高|中等|最低|高|低\nobject:空调\noperate:调成|调低|调高\nposition:\nvalue:',
 'airControl-温度调节': 'mode:温度\ndegree:最高|中等|最低|高|低\nobject:空调\noperate:调成|调高|调低\nposition:\nvalue:',
 'airControl-吹风模式': 'mode:吹风\nobject:空调\noperate:打开|关闭|调成\nposition:',
 'airControl-出风口调节': 'object:出风口\noperate:调成\nposition:\nplace:上|下|左|右|中',
 'cmd-打开和关闭页面': 'mode:页面\nobject:\noperate:打开|关闭',
 'cmd-蓝牙和网络': 'object:蓝牙|wifi|蜂窝移动数据|热点\noperate:打开|关闭|连接|断连',
 'cmd-声音': 'object:\noperate:调高|调低|静音|查询|打开|关闭\nvalue:\nposition:',
 'cmd-屏幕': 'mode:亮度\ndegree:最高|最低|中等\nobject:屏幕|仪表\noperate:调高|调低|调成\nvalue:\nposition:',
 'cmd-壁纸': 'mode:主题|壁纸\ntag:',
 'carControl-车窗': 'object:车窗|车窗锁\noperate:打开|关闭|暂停|调大|调小|调成\nposition:\nvalue:',
 'carControl-天窗': 'object:天窗\noperate:打开|关闭|暂停|调大|调小|调成\nposition:\nvalue:',
 'carControl-遮阳帘': 'object:遮阳帘\noperate:打开|关闭|暂停|调大|调小|调成\nposition:\nvalue:',
 'carControl-座椅加热': 'object:座椅|座椅靠背|座椅坐垫\nmode:加热\noperate:打开|关闭|暂停|调大|调小|调成\ndegree:最高|最低|高|中|低|自动\nposition:\nvalue:',
 'carControl-座椅通风': 'object:座椅|座椅靠背|座椅坐垫\nmode:通风\noperate:打开|关闭|暂停|调高|调低|调成\ndegree:最大|最小|高|中|低|自动\nposition:\nvalue:',
 'carControl-座椅按摩': 'object:座椅\nmode:按摩\nmodeValue:\noperate:打开|关闭|暂停|调高|调低|调成\ndegree:最高|最低|高|中|低|自动\nposition:\nvalue:',
 'carControl-座椅调节': 'object:座椅|座椅后背|座椅靠背\nmode:座椅调节\noperate:前进|后退|向上|向下|向左|向右|调成\ndegree:最前|最后\nposition:\nvalue:',
 'carControl-车门控制': 'object:车门\noperate:打开|关闭|暂停|调大|调小\nposition:',
 'carControl-其他控制': 'object:\nmode:\noperate:打开|关闭|暂停|调高|调低|调成|向左|向右\ndegree:最高|最低|手动\nvalue:\nposition:',
 'vehicleInfo-车辆信息查询':'object:\noperate:查询',
 'telephone-呼叫':'name:\nnumber:\n',
 'telephone-指令':'operate:',
 'app-应用':'object:\noperate:打开|关闭',
 'mapU-导航':'origin:\ndestination:\nstrategy:默认|速度优先|费用优先|躲避拥堵|高速优先|不走高速|大路优先\nwaypoints:',
 'mapU-搜索':'keywords:\nregion:',
 'weather-查询':'object:天气|晴|多云|阴|雨|雾霾|雪|气温\noperate:查询\ncity:\ntime:',
 'musicX-播放歌曲':'operate:播放\nsong:\nauthor:\nsource:\ntag:\nalbum:',
 'video-视频播放':'object:视频\noperate:打开|查询|播放\nauthor:\ntitle:\ntag:\nsource:',
 }


system_message = [{"role": "system", "content": system_content_v2}]
# messages_history = [{"role": "system", "content": system_content},{"role": "user", "content":" "},{"role": "user", "content":""}]
# messages_history = [{"role": "user", "content":" "},{"role": "assistant", "content":" "},{"role": "user", "content":""}]
messages_history = []

openai_api_key = "EMPTY"
openai_api_base = "http://0.0.0.0:10085/v1"

client = OpenAI(
    api_key=openai_api_key,
    base_url=openai_api_base,
)

def chat(query, history_len=2):
    # messages_history.append({"role": "user", "content": query})
    messages_now = [{"role": "user", "content": query}]
    # print(f"LOG:{messages_history}")
    messages = system_message + messages_history + messages_now
    chat_response = client.chat.completions.create(
        # model="base_model",
        model="nlu_model",
        messages=messages,
        max_tokens=64,
        temperature=0.2,
        extra_body={
            "chat_template_kwargs": {"enable_thinking": False},
        },
    )
    # print(messages)
    for m in messages:
        if m['role'] != "system":
            print(m)
    query_rewritten = chat_response.choices[0].message.content
    
    messages_history.append({"role": "user", "content": query_rewritten})

    # messages_history.append({"role": "user", "content": query})
    # messages_history.append({"role": "assistant", "content": query_rewritten})

    chat_response = client.chat.completions.create(
        # model="4B-2507",
        # model="8B_v2",
        model="lora_domain",
        messages=[
            {"role": "system", "content": system_content_domain_v4},
            {"role": "user", "content": query_rewritten},
        ],
        max_tokens=128,
        temperature=0.2,
        extra_body={
            "chat_template_kwargs": {"enable_thinking": False},
        },
    )
    res = chat_response.choices[0].message.content

    
    # if len(messages_history)//2 > history_len:
    #     messages_history.pop(0)
    #     messages_history.pop(0)
    
    if len(messages_history) > history_len:
        messages_history.pop(0)

    # print("Chat response:", chat_response)
    # return f"query old: {query}\nquery new: {query_rewritten}\nanswer: {res}"
    return [query,query_rewritten,res]

def nlu(query):
    chat_response = client.chat.completions.create(
        model="lora_domain",
        messages=[
            {"role": "system", "content": system_content_classify},
            {"role": "user", "content": query},
        ],
        max_tokens=16,
        temperature=0.2,
        extra_body={
            "chat_template_kwargs": {"enable_thinking": False},
        },
    )
    res = chat_response.choices[0].message.content
    if res in domain_en_dict:
        domain = domain_en_dict[res]
    else:
        domain = "other"
    
    result = {"text": query, "domain": domain, "intent": ""}
    intent = res
    if domain in intent_dict:
        
        intent_content = {"text":{query},"domain":{domain},"intent":intent_dict[domain]}
        response = client.chat.completions.create(
            model="lora_domain", # 根据实际模型调整
            #model="nlu_model",
            messages=[
                {"role": "system", "content": system_content_intent},
                {"role": "user", "content": f"{intent_content}"} # 用户消息内容可以很简单，因为所有信息都在系统提示中
            ],
            temperature=0.3,
            max_tokens=16,
            extra_body={"chat_template_kwargs": {"enable_thinking": False}}
        )
        intent=response.choices[0].message.content
        # result = {"text": query, "domain": res, "intent": ""}
        result['intent']=intent   
    semantic_slot = {}
    semantic_content = {"text":query,"domain":domain,"intent":intent,"slot":semantic_slot} 

    if domain in semantic_dict and intent in semantic_dict[domain]:
        semantic_slot = semantic_dict[domain][intent]
        semantic_content["slot"] = semantic_slot

        semantic_response = client.chat.completions.create(
            model="lora_semantic",
            messages=[
                {"role": "system", "content": system_content_semantic},
                {"role": "user", "content": json.dumps(semantic_content)},
            ],
            temperature=0.3,
            max_tokens=64,
            extra_body={"chat_template_kwargs": {"enable_thinking": False}}
        )
        semantic=semantic_response.choices[0].message.content
        # print(semantic)
        # semantic_json = json.loads(semantic)
        semantic_json = ast.literal_eval(semantic)
        return semantic_json

    return semantic_content

def nlu_v1(query):
    chat_response = client.chat.completions.create(
        model="lora_domain",
        messages=[
            {"role": "system", "content": system_content_classify},
            {"role": "user", "content": query},
        ],
        max_tokens=16,
        temperature=0.2,
        extra_body={
            "chat_template_kwargs": {"enable_thinking": False},
        },
    )
    res = chat_response.choices[0].message.content
    if res in domain_en_dict:
        domain = domain_en_dict[res]
    else:
        domain = "other"
    
    result = {"text": query, "domain": domain, "intent": ""}
    intent = res
    if domain in intent_dict:
        
        intent_content = {"text":{query},"domain":{domain},"intent":intent_dict[domain]}
        response = client.chat.completions.create(
            model="lora_domain", # 根据实际模型调整
            #model="nlu_model",
            messages=[
                {"role": "system", "content": system_content_intent},
                {"role": "user", "content": f"{intent_content}"} # 用户消息内容可以很简单，因为所有信息都在系统提示中
            ],
            temperature=0.3,
            max_tokens=16,
            extra_body={"chat_template_kwargs": {"enable_thinking": False}}
        )
        intent=response.choices[0].message.content
        # result = {"text": query, "domain": res, "intent": ""}
        result['intent']=intent   

    result = {"text": query, "domain": domain, "intent": intent, "slot": {}}
    domain_intent = f"{domain}-{intent}"
    # semantic_content = f"domain:{domain}\nintent:{intent}\ntext:{query}\n{semantic_tmp[domain_intent]}"
    if domain_intent in semantic_tmp:
        semantic_slot = semantic_tmp[domain_intent]
        semantic_content = f"domain:{domain}\nintent:{intent}\ntext:{query}\n{semantic_tmp[domain_intent]}"

        semantic_response = client.chat.completions.create(
            model="lora_semantic",
            messages=[
                {"role": "system", "content": system_content_semantic_v1},
                {"role": "user", "content": semantic_content},
            ],
            temperature=0.3,
            max_tokens=64,
            extra_body={"chat_template_kwargs": {"enable_thinking": False}}
        )
        slot = {}
        for pair in semantic_response.choices[0].message.content.strip().split('\n'):  # 按行拆分
            key, value = pair.split(':', 1)        # 仅分割第一个冒号，避免值中含冒号
            slot[key.strip()] = value.strip() 
        result["slot"] = slot

    return result

if __name__ == "__main__":
    # history_len = int(sys.argv[1])
    # while True:
    #     query = input("query: ")
    #     query,query_rewritten,res = chat(query, history_len)
    #     print(f"query new: {query_rewritten}\ndomain: {res}\n=============")
    while True:
        query = input("query: ")
        semantic = nlu_v1(query)
        print(f"semantic v1: {semantic}")
        semantic = nlu(query)
        print(f"semantic : {semantic}")